home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Source Code
/
Visual Basic Source Code.iso
/
vbsource
/
vblock
/
vblock.txt
< prev
Wrap
Text File
|
1991-09-01
|
12KB
|
330 lines
ALLOCATING PROTECTED MEMORY IN VISUAL BASIC
by Brent K. Langley CSID: 70312,2142
This document contains some memory pointers (pun intended) for securing
fixed memory buffer allocations from Visual BASIC.
As far as I understand it, you've got your choice of two places
where memory can be allocated: Locally (I guess that this would be
Visual BASIC's own local heap) or globally (all the rest of available
memory). Window's memory management doesn't give you a physical address
when you allocate memory (using API calls) but rather a "handle" that it
can cross reference to the correct memory location when it needs to. When
not needed, it is free to move the block around in your system's memory
space to allow for reorganization of fragmented memory chunks and to
make larger contiguous memory areas. Programmers are warned in Windows
that physical memory location pointers are transient and might be changed
if something happens to request a big block of memory. Some movement of
memory blocks is just shifts in linear memory space. Some moves are in
and out of EMS memory banks (if you have EMS memory boards). Some are in and
out and around in extended memory (on 286 and better machines.) And some
memory swaps are actually paged to disk (this is why you see your disk light
blink a lot when you have a lot of programs active i.e. in and out of the TEMP
subdirectory area of your disk.)
To get a physical memory address, you have to de-reference the handle to
find out where the block currently is in memory land. BUT VB passes you
an address of an already de-referenced block in a DLL call. As soon as you
get this address, you can call an API function to get the handle and then ask
Windows to protect it's location. There are several ways to do this.
Lock will add to a counter, indicating the number of apps that don't want
a memory block to move. Its unclear from the SDK docs, but Locked doesn't
always seem to mean that its really Locked.
Sooooo, you can Wire a memory block. This makes sure that the block of memory
is below the EMS line (it won't get paged out to EMS memory behind your
back) and it gets locked. Wire will move memory if necessary to get your block
below this "EMS line", so your original pointer is no longer valid.
Also, with extended memory things can shift around, so there are functions
that do a PageLock for that kind of protection.
The SDK docs say that for compatibility, the malloc and calloc functions
will automatically lock your memory locations for you (but I don't know
what kind of locks)
When you no longer need the data to be fixed in memory, you should unlock,
unwire, unpagelock, ... undo whatever you did to be nice to Windows
memory management system.
If anyone else reads this and can provide any deeper enlightenment into
the ways of memory locks and stuff, please hop in!
I've included some code that I wrote to lock a couple of ways: completely
in VB, or with DLL routines that allocate locked data for VB to play with.
Although this code calls some routines that I have not uploaded (add_group,
send_datagram, and delete_name) I think they can show you how to use these
routines in your own programs. Notice that my nballoc returns a long integer
that is really a far pointer to the locked memory space. Use LSTRCPY to copy
the contents of this allocated buffer to or from a VB string. Any DLL function
that requires a parameter of type ByVal As String could be changed to As Any.
(see the bottom of page 385 in the VB Programmer's Guide.) Then when passing
a string, the routine gets the address of the string. When passing a value
returned by my alloc routines, send ByVal <Variable> so that the contents
(i.e. the memory location of the buffer) is passed to the DLL, not the address
of your variable called <Variable>.
Of course, you can also do all memory allocation/deallocation from completely
within a DLL using Window's API calls or with malloc and free. But since
this was sent mainly to help VB People (VB'ers VBites VBees what are we?) I
won't take up space with purely C programming.
/*--------------------------------------------------------------------*/
/* NBMEMORY.C to make NBMEMORY.DLL by Brent K. Langley 9/1/91 */
/*--------------------------------------------------------------------*/
/* Code to allocate memory from the global heap and lock it in place */
/* This code will make a DLL that can be called from Visual BASIC */
/* Code was originally made to create network buffers that had to */
/* stay in place, waiting for a hardware interrupt to access them. */
/* In the meantime, Window's memory management should not try to move*/
/* them around. .... Brent K. Langley CSID: 70312,2142 */
/*--------------------------------------------------------------------*/
#include <windows.h>
/* Visual BASIC Declaration Format: */
/* Declare Function nballoc Lib "nbmemory.dll" (ByVal size As Long) As Long */
char far * far pascal _export nballoc( unsigned long size )
{
unsigned mHandle;
char far * mPtr;
mHandle = GlobalAlloc( GMEM_FIXED |
GMEM_NOT_BANKED |
GMEM_ZEROINIT |
GMEM_NODISCARD, size );
if ( mHandle == 0 ) return 0; /* couldn't get memory allocated */
mPtr = GlobalWire( mHandle );
if ( mPtr == 0 ) /* couldn't "wire" memory block then */
mPtr = GlobalLock( mHandle ); /* maybe we can just lock it in place */
GlobalPageLock( mHandle ); /* don't let it get virtually paged */
return mPtr; /* returns far pointer or 0 if unlocked */
}
/* Visual BASIC Declaration format: */
/* Declare Function nbfree Lib "nbmemory.dll" (mPtr As Long) As Integer */
int far pascal _export nbfree( char far * mPtr )
{
unsigned mHandle;
mHandle = GlobalHandle( (unsigned long) mPtr & 0xFFFF ); /*get handle of ptr*/
GlobalPageUnlock( mHandle );
GlobalUnWire( mHandle );
return ! GlobalFree( mHandle ); /*Return TRUE if free/FALSE if still locked*/
}
int FAR PASCAL LibMain( HANDLE hInstance, WORD wDataSeg,
WORD cbHeapSize, LPSTR lpCmdLine)
{
return 1 ;
}
int FAR PASCAL WEP ( int nParmeter )
{
return 1;
}
'------------------------------------------------------------
' Visual BASIC Global Declarations section
'------------------------------------------------------------
' Global Memory Flags
Global Const GMEM_FIXED = &H0
Global Const GMEM_MOVEABLE = &H2
Global Const GMEM_NOCOMPACT = &H10
Global Const GMEM_NODISCARD = &H20
Global Const GMEM_ZEROINIT = &H40
Global Const GMEM_MODIFY = &H80
Global Const GMEM_DISCARDABLE = &H100
Global Const GMEM_NOT_BANKED = &H1000
Global Const GMEM_SHARE = &H2000
Global Const GMEM_DDESHARE = &H2000
Global Const GMEM_NOTIFY = &H4000
Global Const GMEM_LOWER = GMEM_NOT_BANKED
Global Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
Global Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
Declare Function GlobalAlloc Lib "Kernel" (ByVal wFlags As Integer, ByVal dwBytes As
Long) As Integer
Declare Function GlobalFree Lib "Kernel" (ByVal hMem As Integer) As Integer
Declare Function GlobalHandle Lib "Kernel" (ByVal wMem As Integer) As Long
Declare Function GlobalLock Lib "Kernel" (ByVal hMem As Integer) As Long
Declare Function GlobalUnlock Lib "Kernel" (ByVal hMem As Integer) As Integer
Declare Function GlobalWire Lib "Kernel" (ByVal hMem As Integer) As Long
Declare Function GlobalUnWire Lib "Kernel" (ByVal hMem As Integer) As Integer
Declare Function GlobalPageLock Lib "Kernel" (ByVal wSelector As Integer) As Integer
Declare Function GlobalPageUnlock Lib "Kernel" (ByVal wSelector As Integer) As
Integer
Declare Sub GlobalFix Lib "Kernel" (ByVal hMem As Integer)
Declare Function GlobalUnfix Lib "Kernel" (ByVal hMem As Integer) As Integer
'---------------------------------------------------